<template>
  <div
    class="scroll-wrap"
    @mouseenter="paused = true"
    @mouseleave="paused = false"
  >
    <!-- 表头 -->
    <div class="header">
      <div class="cell2">使用时间</div>
      <div class="cell">所在楼层</div>
      <div class="cell">房间状态</div>
    </div>

    <!-- 滚动区域 -->
    <div class="viewport" :style="{ height: visibleRows * rowHeight + 'px' }">
      <div class="scroller" :style="{ transform: `translateY(${-offset}px)` }">
        <!-- 第一份 -->
        <div v-for="(row, i) in dataSource" :key="'a-' + i" class="row">
          <div class="cell2">{{ row.name }}</div>
          <div class="cell">{{ row.dept }}</div>
          <div class="cell">{{ row.score }}</div>
        </div>
        <!-- 第二份，克隆用于无缝 -->
        <div v-for="(row, i) in dataSource" :key="'b-' + i" class="row">
          <div class="cell2">{{ row.name }}</div>
          <div class="cell">{{ row.dept }}</div>
          <div class="cell">{{ row.score }}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
const props = withDefaults(
  defineProps<{
    dataSource: { name: string; dept: string; score: number }[];
    visibleRows?: number;
    rowHeight?: number;
    speed?: number; // 每帧滚动像素
  }>(),
  {
    dataSource: () => [
      {
        name: "张三",
        dept: "研发部",
        score: 100,
      },
      {
        name: "李四",
        dept: "市场部",
        score: 90,
      },
      {
        name: "王五",
        dept: "运营部",
        score: 80,
      },
      {
        name: "赵六",
        dept: "人事部",
        score: 70,
      },
      {
        name: "钱七",
        dept: "财务部",
        score: 60,
      },
    ],
    visibleRows: 6,
    rowHeight: 40,
    speed: 0.5,
  }
);

const offset = ref(0);
const paused = ref(false);
let rafId: number | null = null;

// 一份列表总高度
const listHeight = computed(() => props.dataSource.length * props.rowHeight);

// 滚动逻辑
function loop() {
  if (!paused.value) {
    offset.value += props.speed;
    if (offset.value >= listHeight.value) {
      offset.value = 0;
    }
  }
  rafId = requestAnimationFrame(loop);
}

onMounted(() => {
  rafId = requestAnimationFrame(loop);
});
onBeforeUnmount(() => {
  if (rafId) cancelAnimationFrame(rafId);
});
</script>

<style scoped>
.scroll-wrap {
  width: 100%;
  height: 100%;
  font-size: 14px;
  user-select: none;
  overflow: hidden;
}
.header {
  width: 100%;
  height: 28px;
  display: flex;
  align-items: center;
  font-weight: bold;
  background: rgb(71, 106, 160);
  font-size: 14px;
  color: #b3d1ff;
}
.viewport {
  overflow: hidden;
  position: relative;
  font-size: 14px;
  color: #d8f0ff;
  background: rgb(132, 166, 216);
}
.scroller {
  will-change: transform;
}
.row {
  display: flex;
  height: 28px;
  line-height: 28px;
}
.row:hover {
  background: linear-gradient(
    270deg,
    rgba(26, 123, 230, 0) 0%,
    rgba(69, 193, 255, 0.7) 100%
  );
}
.cell {
  flex: 1;
  padding: 0 8px 0 16px;
}
.cell2 {
  flex: 2;
  padding: 0 8px 0 16px;
}
</style>